#include "key_drv.h"
#include "systick.h"

static Key_Info_t g_keyInfo[KEY_NUM_MAX];

/**
 * @brief 按键硬件初始化
 * @param
 * @return
 */
void KeyDrvInit(void)
{
    gpio_init_type gpio_init_struct;

    gpio_default_para_init(&gpio_init_struct);

    gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;              /* 推挽输出 */
    gpio_init_struct.gpio_pull = GPIO_PULL_UP;                           /* 无上拉 */
    gpio_init_struct.gpio_mode = GPIO_MODE_INPUT;                        /* 输出模式 */

    for (uint8_t i = 0; i < KEY_NUM_MAX; i++)
    {
        gpio_init_struct.gpio_pins = g_gpioList[i].pin;
        gpio_init(g_gpioList[i].gpio, &gpio_init_struct);
    }
}

/**
 * @brief 判断按键是否按下
 * @param _id 按键编号
 * @return 返回值：1 表示按下，0 表示未按下
 */
static uint8_t KeyPinActive(uint8_t _id)
{
    return (gpio_input_data_bit_read(g_gpioList[_id].gpio, g_gpioList[_id].pin) == g_gpioList[_id].ActiveLevel);
}

/**
 * @brief 按键扫描
 * @param keyIndex 按键编号
 */
static uint8_t KeyScan(uint8_t keyIndex)
{
    volatile uint64_t curSysTime;
    uint8_t keyPress;

    keyPress = KeyPinActive(keyIndex);

    switch (g_keyInfo[keyIndex].keyState)
    {
    case KEY_RELEASE: /* 释放状态，判断有无按键按下 */
        if (keyPress) /* 按键按下 */
        {
            g_keyInfo[keyIndex].keyState = KEY_CONFIRM;
            g_keyInfo[keyIndex].firstIoChangeSysTime = GetSysRunTime();
            break;
        }
        if (g_keyInfo[keyIndex].singleClickNum != 0)
        {
            curSysTime = GetSysRunTime();
            if (curSysTime - g_keyInfo[keyIndex].firstIoChangeSysTime > DOUBLE_CLICK_INTERVAL_TIME)
            {
                g_keyInfo[keyIndex].singleClickNum = 0;
                return (keyIndex + 0x01); /* 返回单击按键码值，三个按键短按对应0x01, 0x02, 0x03 */
            }
        }
        break;

    case KEY_CONFIRM: /* 消抖状态 */
        if (keyPress) /* 按键按下 */
        {
            curSysTime = GetSysRunTime();
            if (curSysTime - g_keyInfo[keyIndex].firstIoChangeSysTime > CONFIRM_TIME)
            {
                g_keyInfo[keyIndex].keyState = KEY_SHORTPRESS;
            }
        }
        else
        {
            g_keyInfo[keyIndex].keyState = KEY_RELEASE;
        }
        break;

    case KEY_SHORTPRESS: /* 短按状态：继续判定是短按，还是双击，还是长按 */
        if (keyPress)    /* 按键按下 */
        {
            curSysTime = GetSysRunTime();
            if (curSysTime - g_keyInfo[keyIndex].firstIoChangeSysTime > LONGPRESS_TIME) /* 超过长按时间间隔 */
            {
                g_keyInfo[keyIndex].keyState = KEY_LONGPRESS;
            }
        }
        else
        {
            g_keyInfo[keyIndex].keyState = KEY_RELEASE;

            g_keyInfo[keyIndex].singleClickNum++;
            if (g_keyInfo[keyIndex].singleClickNum == 1)
            {
                g_keyInfo[keyIndex].firstReleaseSysTime = GetSysRunTime();
                break;
            }
            else
            {
                curSysTime = GetSysRunTime();
                if (curSysTime - g_keyInfo[keyIndex].firstReleaseSysTime <= DOUBLE_CLICK_INTERVAL_TIME) /* 超过双击时间间隔，返回双击码值 */
                {
                    g_keyInfo[keyIndex].singleClickNum = 0;
                    return (keyIndex + 0x51); /* 返回按键码值，三个按键双击对应0x51, 0x52, 0x53 */
                }
            }
        }
        break;

    case KEY_LONGPRESS: /* 长按状态 */
        if (keyPress)   /* 按键按下 */
        {
            return (keyIndex + 0x81); /* 返回按键码值，三个按键长按对应0x81, 0x82, 0x83 */
        }
        else
        {
            g_keyInfo[keyIndex].keyState = KEY_RELEASE;
        }
        break;

    default:
        g_keyInfo[keyIndex].keyState = KEY_RELEASE;
        break;
    }
    return 0;
}

/**
 * @brief 获取按键码值
 * @param
 * @return 四个按键码值，短按0x01 0x02 0x03
 *                      双击0x51 0x52 0x53
 *                      长按0x81 0x82 0x83
 *                      没有按下为0
 */
uint8_t GetKeyVal(void)
{
    uint8_t res = 0;

    for (uint8_t i = 0; i < KEY_NUM_MAX; i++)
    {
        res = KeyScan(i);
        if (res != 0)
        {
            break;
        }
    }
    return res;
}

/**
 * @brief 按键测试
 * @param
 */
// void KeyDrvTest(void)
// {
//     static uint8_t i = 0;
//     uint8_t keyVal = GetKeyVal();
//     switch (keyVal)
//     {
//     case KEY1_SHORT_PRESS:
//         i++;
//         // printf("key1 short press\n");
//         LedDrvSet(LEDG1, FALSE);
//         LedDrvSet(LEDG2, FALSE);
//         break;
//     case KEY1_DOUBLE_PRESS:
//         i++;
//         LedDrvSet(LEDG1, TRUE);
//         LedDrvSet(LEDG2, FALSE);
//         // printf("key1 double press\n");
//         break;
//     case KEY1_LONG_PRESS:
//         i++;
//         LedDrvSet(LEDG1, TRUE);
//         LedDrvSet(LEDG2, FALSE);
//         // printf("key1 long press\n");
//         break;
//     case KEY2_SHORT_PRESS:
//         i++;
//         LedDrvSet(LEDG1, TRUE);
//         LedDrvSet(LEDG2, FALSE);
//         // printf("key1 short press\n");
//         break;
//     case KEY2_DOUBLE_PRESS:
//         i++;
//         LedDrvSet(LEDG1, TRUE);
//         LedDrvSet(LEDG2, FALSE);
//         // printf("key1 double press\n");
//         break;
//     case KEY2_LONG_PRESS:
//         i++;
//         LedDrvSet(LEDG1, TRUE);
//         LedDrvSet(LEDG2, FALSE);
//         // printf("key1 long press\n");
//         break;
//     case KEY3_SHORT_PRESS:
//         i++;
//         LedDrvSet(LEDG1, TRUE);
//         LedDrvSet(LEDG2, TRUE);
//         // printf("key1 short press\n");
//         break;
//     case KEY3_DOUBLE_PRESS:
//         i++;
//         LedDrvSet(LEDG2, TRUE);
//         LedDrvSet(LEDG1, TRUE);
//         // printf("key1 double press\n");
//         break;
//     case KEY3_LONG_PRESS:
//         i++;
//         LedDrvSet(LEDG1, TRUE);
//         LedDrvSet(LEDG2, TRUE);
//         // printf("key1 long press\n");
//         break;
//     default:
//         break;
//     }
// }
